package com.pactera.generator;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: pactera_module
 * @description: 代码生成器
 * @author: EC_liqingdian
 * @create: 2019-12-13 15:13
 **/
public class Generator {

    private Generator() {
    }

    private static class Inner {
        private static final Generator instance = new Generator();
    }

    public static Generator getInstance() {
        return Inner.instance;
    }

    /**
     * 构建生成器
     *
     * @Author: EC_liqingdian
     * @Modify:
     * @Date: 2019/12/13
     */
    public AutoGenerator build() {
        AutoGenerator generator = new AutoGenerator();
        // 全局配置
        generator.setGlobalConfig(this.globalConfig());
        // 数据库配置
        generator.setDataSource(this.dataSourceConfig());
        // 包配置
        generator.setPackageInfo(this.packageConfig());
        // 策略配置
        generator.setStrategy(this.strategyConfig());
        // 自定义属性注入配置
        generator.setCfg(this.injectionConfig4Resources());
        // 模板配置
        generator.setTemplate(this.templateConfig());
        return generator;
    }

    /**
     * 全局配置
     *
     * @Author: EC_liqingdian
     * @Modify:
     * @Date: 2019/12/13
     */
    private GlobalConfig globalConfig() {
        GlobalConfig globalConfig = new GlobalConfig();
        // 输出目录
        StringBuilder mkdir = this.mkdir();
        mkdir.append(File.separator);
        mkdir.append("java");
        globalConfig.setOutputDir(mkdir.toString());
        // 生成操作员名称
        globalConfig.setAuthor("admin");
        // 是否覆盖文件
        globalConfig.setFileOverride(true);
        // 开启 activeRecord 模式
        globalConfig.setActiveRecord(false);
        // XML 二级缓存
        globalConfig.setEnableCache(false);
        // XML ResultMap
        globalConfig.setBaseResultMap(false);
        // XML columList
        globalConfig.setBaseColumnList(false);
        //生成后打开文件夹
        globalConfig.setOpen(true);
        globalConfig.setSwagger2(false);
        // 自定义文件命名，注意 %s 会自动填充表实体属性
        globalConfig.setEntityName("%sDto");
        globalConfig.setMapperName("%sMapper");
        globalConfig.setXmlName("%sMapper");
        globalConfig.setServiceName("%sService");
        globalConfig.setServiceImplName("%sServiceImpl");
        globalConfig.setControllerName("%sController");
        return globalConfig;
    }

    private StringBuilder mkdir() {
        StringBuilder mkdir = new StringBuilder();
        mkdir.append(System.getProperty("user.dir"));
        mkdir.append(File.separator);
        mkdir.append("src");
        mkdir.append(File.separator);
        mkdir.append("main");
        return mkdir;
    }

    /**
     * 数据库配置
     *
     * @Author: EC_liqingdian
     * @Modify:
     * @Date: 2019/12/13
     */
    private DataSourceConfig dataSourceConfig() {
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        // 数据库类型
        dataSourceConfig.setDbType(DbType.MYSQL);
        // 数据库驱动类全路径
        dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
        // 数据库连接url
        dataSourceConfig.setUrl("jdbc:mysql://127.0.0.1:3306/my_test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC");
        // 数据库用户名
        dataSourceConfig.setUsername("root");
        // 数据库密码
        dataSourceConfig.setPassword("root");
        // 数据库类型转换
        dataSourceConfig.setTypeConvert(new ITypeConvert() {
            public IColumnType processTypeConvert(com.baomidou.mybatisplus.generator.config.GlobalConfig globalConfig, String fieldType) {
                String field = fieldType.toLowerCase();
                if (field.contains("tinyint")) {
                    return DbColumnType.INTEGER;
                }
                if (field.contains("date") || field.contains("time")) {
                    return DbColumnType.DATE;
                }
                return new MySqlTypeConvert().processTypeConvert(globalConfig, fieldType);
            }
        });
        return dataSourceConfig;
    }

    /**
     * 包路径配置
     *
     * @Author: EC_liqingdian
     * @Modify:
     * @Date: 2019/12/13
     */
    private PackageConfig packageConfig() {
        PackageConfig packageConfig = new PackageConfig();
        // 自定义包路径
        packageConfig.setParent("com.pactera");
        // 设置Entity包名，默认entity
        packageConfig.setEntity("dto");
        // 设置Mapper包名，默认mapper
        packageConfig.setMapper("mapper");
        // 设置Mapper XML包名，默认mapper.xml
        packageConfig.setXml("xml");
        packageConfig.setModuleName("demo");
        packageConfig.setController("controller");// 这里是控制器包名，默认 web
        packageConfig.setService("service"); // 设置Service包名，默认service
        packageConfig.setServiceImpl("service.impl"); // 设置Service Impl包名，默认service.impl
        return packageConfig;
    }

    /**
     * 策略配置
     *
     * @Author: EC_liqingdian
     * @Modify:
     * @Date: 2019/12/13
     */
    private StrategyConfig strategyConfig() {
        StrategyConfig strategyConfig = new StrategyConfig();
        // 表前缀
        String[] tablePrefixs = new String[]{
                "a_", "b_", "c_", "d_", "e_",
                "f_", "g_", "h_", "i_", "j_",
                "k_", "l_", "m_", "n_", "o",
                "p_", "q_", "r_", "s_", "t_",
                "u_", "v_", "w_", "x_", "y_",
                "z_", "sys_"
        };
        strategyConfig.setTablePrefix(tablePrefixs);
        // 表名生成策略
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
        // 生成的Controller类添加注解@RestController
        strategyConfig.setRestControllerStyle(true);
        // 【实体】是否为lombok模型（默认 false）
        strategyConfig.setEntityLombokModel(false);
        return strategyConfig;
    }

    /**
     * 自定义属性注入配置
     *
     * @Author: EC_liqingdian
     * @Modify:
     * @Date: 2019/12/13
     */
    public InjectionConfig injectionConfig4Java(PackageConfig packageConfig) {
        InjectionConfig injectionConfig = new InjectionConfig() {
            public void initMap() {
                Map<String, Object> map = new HashMap<>();
                // 模板的${package}
                map.put("package", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
                this.setMap(map);
            }
        };
        List<FileOutConfig> fileOutList = new ArrayList<>();
        // 指定模板文件
        fileOutList.add(new FileOutConfig("/templates/mapper.xml.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                StringBuilder mkdir = mkdir();
                mkdir.append(File.separator);
                mkdir.append("java");
                String basePackage = packageConfig.getParent();
                String[] packages = basePackage.split("\\.");
                for (int i = 0; i < packages.length; i++) {
                    mkdir.append(File.separator).append(packages[i]);
                }
                mkdir.append(File.separator).append("mapper").append(File.separator).append("xml");
                mkdir.append(File.separator).append(tableInfo.getEntityName()).append("Mapper.xml");
                return mkdir.toString();
            }
        });
        injectionConfig.setFileOutConfigList(fileOutList);
        return injectionConfig;
    }

    /**
     * 自定义属性注入配置
     *
     * @Author: EC_liqingdian
     * @Modify:
     * @Date: 2019/12/13
     */
    private InjectionConfig injectionConfig4Resources() {
        InjectionConfig injectionConfig = new InjectionConfig() {
            public void initMap() {
                Map<String, Object> map = new HashMap<>();
                // 模板的${package}
                map.put("package", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
                this.setMap(map);
            }
        };
        List<FileOutConfig> fileOutList = new ArrayList<>();
        // 指定模板文件
        fileOutList.add(new FileOutConfig("/templates/mapper.xml.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                StringBuilder mkdir = mkdir();
                mkdir.append(File.separator);
                mkdir.append("resources").append(File.separator).append("mapper");
                mkdir.append(File.separator).append(tableInfo.getEntityName()).append("Mapper.xml");
                return mkdir.toString();
            }
        });
        injectionConfig.setFileOutConfigList(fileOutList);
        return injectionConfig;
    }

    /**
     * 模板配置
     *
     * @Author: EC_liqingdian
     * @Modify:
     * @Date: 2019/12/13
     */
    private TemplateConfig templateConfig() {
        TemplateConfig templateConfig = new TemplateConfig();
        // 关闭默认 xml 生成，调整生成 至 根目录
        templateConfig.setXml(null);
        templateConfig.setServiceImpl(null);
        templateConfig.setService(null);
        templateConfig.setController(null);
        // 自定义模板配置，模板可以参考源码 /mybatis-plus/src/main/resources/template 使用 copy
        // 至您项目 src/main/resources/template 目录下，模板名称也可自定义如下配置：
        return templateConfig;
    }
}
